import React, { CSSProperties, ReactNode } from 'react';
import { LinkProps } from 'react-router-dom';
import { Avatar, Badge, Checkbox, Divider, Dropdown, Menu, Modal, Popconfirm, Popover, Progress, Radio, Rate, Slider, Space, Switch, Table, Tag, Tooltip } from 'antd';
import { ColumnProps, TablePaginationConfig, TableProps } from 'antd/es/table';
import { RowSelectionType, SorterResult, SortOrder, TableRowSelection } from 'antd/es/table/interface';
import { AvatarProps } from 'antd/es/avatar';
import { BadgeProps } from 'antd/es/badge';
import { PopoverProps } from 'antd/es/popover';
import { TooltipProps } from 'antd/es/tooltip';
import { TagProps } from 'antd/es/tag';
import { ProgressProps } from 'antd/es/progress';
import { PopconfirmProps } from 'antd/es/popconfirm';
import { ModalFuncProps } from 'antd/es/modal';
import { SwitchProps } from 'antd/es/switch';
import { RadioGroupProps, RadioProps } from 'antd/es/radio';
import { CheckboxGroupProps, CheckboxProps } from 'antd/es/checkbox';
import { RateProps } from 'antd/es/rate';
import { SizeType } from 'antd/es/config-provider/SizeContext';
import { EllipsisOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import lodash from 'lodash';
import { stringify } from 'qs';
import {
  EnumArrayItem,
  getMapperDataItem,
  getServerData,
  getServerTableData,
  ServerDataConfig,
  ServerDataDefaultConfig,
  ServerTableDataConfig,
  ServerTableDataDefaultConfig,
  hasValue,
  TypeEnum,
  variableTypeOf,
  bytesFormat,
  dateToStr,
  howLong,
  howLongAgo,
  toDayjs,
  dateSubtract,
  UmiLink,
  numberFormat,
} from '@/common';
import { FieldSort, sortDataSet } from '@/common/data-set';
import {
  TableRowData,
  TableColumn,
  TableColumnAction,
  ModalDialogProps,
  ReloadParams,
  ReloadModel,
  BasePropsItem,
  DataValueType,
  DataWrapperType,
  AntdSliderProps,
  ActionType,
  GetLocalDataSourceRes,
} from './table-types';
// import styles from './DataTable.less';

// Model 初始化值配置
const TableDefaultPagination: TablePaginationConfig = {
  size: 'default',
  defaultCurrent: 1,
  defaultPageSize: 10,
  hideOnSinglePage: false,
  pageSizeOptions: ['10', '30', '50', '100', '150', '200'],
  showSizeChanger: true,
  showQuickJumper: true,
  showTitle: true,
  // TODO 国际化
  showTotal: (total: number, range: [number, number]) => `第${range[0]}~${range[1]}条，共${total}条`,
  total: 0,
};

interface DataTableProps {
  // ----------------------------------------------------------------------------------- 初始值
  /** 初始化本地数据 */
  initLocalDataSource?: TableRowData[];
  /** 初始化分页器配置，可用于还原Table数据状态 */
  initPagination?: boolean | TablePaginationConfig;

  // ----------------------------------------------------------------------------------- 核心配置
  /** 是否显示序号列(数据索引) */
  indexColumn?: boolean | ((index: number, record: TableRowData) => ReactNode);
  /** 表格行选择模式 */
  selectionMode?: RowSelectionType;
  /** 表格行选择扩展配置 */
  rowSelection?: Partial<TableRowSelection<TableRowData>>;
  /** 全局数据格式化配置 */
  formatter?: {
    /** 数字格式化配置,使用"numeral"库实现格式化 */
    number?: string | ((data: number) => ReactNode);
    /** 金额格式化,使用"numeral"库实现格式化 */
    money?: string | ((data: number) => ReactNode);
    /** 日期格式化,使用"moment"库实现格式化 */
    date?: string | ((data: any) => ReactNode);
    /** 日期时间格式化,使用"moment"库实现格式化 */
    datetime?: string | ((data: any) => ReactNode);
    /** 时间格式化,使用"moment"库实现格式化 */
    time?: string | ((data: any) => ReactNode);
    /** TimeBefore格式化使用 */
    timeBeforeFmt?: {
      /** 需要显示的层级(默认3) */
      level?: number;
      /** 转换的最大时间差距(默认7天) */
      maxTimeStamp?: number;
      /** 时间单位数组，默认值 ["年", "个月", "天", "小时", "分钟", "秒"] */
      timeUnit?: string[];
    };
    /** HowLongTime格式化使用 */
    howLongTimeFmt?: {
      /** 需要显示的层级(默认3) */
      level?: number;
      /** 时间单位数组，默认值 ["Y", "M", "D", "h", "m", "s", "ms"] */
      timeUnit?: string[];
    };
  };
  /** 表格列配置 */
  columns: TableColumn[];
  /** 操作列的操作项 */
  columnActions?: TableColumnAction[];
  /** 操作列宽度 */
  columnActionWidth?: number;
  /** 最多显示多少个操作项，过多的操作项将会在“更多”列表下 */
  maxActionItem?: number;
  /** 更多操作按钮 */
  moreActionButton?: ReactNode;
  /** 表格行 key 的取值 */
  rowKey: string | ((record: TableRowData) => string);
  /** 表格大小 */
  size?: SizeType;
  /** 是否需要边框 */
  bordered?: boolean;
  /** 获取服务端数据配置(服务端分页数据源) */
  serverPaginationData?: ServerTableDataConfig<TableRowData>;
  /** 获取服务端数据配置(不支持分页) */
  serverData?: ServerDataConfig<TableRowData[]>;
  /** loading变化事件 */
  onLoadingChange?: (loading: boolean) => void;
  // ----------------------------------------------------------------------------------- 扩展配置
  /** Table属性 */
  tableProps?: TableProps<TableRowData>;
  /** 当前组件自定义样式 */
  style?: CSSProperties;
  /** 当前组件自定义class样式 */
  className?: string;

  /** 表格行自定义class样式 */
  rowClassName?: string;
}

// tableLayout
// bordered	是否展示外边框和列边框
// components	覆盖默认的 table 元素
// expandable 配置展开属性
// footer 表格尾部
// locale	默认文案设置
// rowSelection	表格行是否可选择
// scroll	表格是否可滚动，也可以指定滚动区域的宽、高
// showHeader	是否显示表头
// summary	总结栏
// title	表格标题
// onChange	分页、排序、筛选变化时触发
// onHeaderRow	设置头部行属性
// onRow	设置行属性
// getPopupContainer	设置表格内各类浮层的渲染节点，如筛选菜单
// sortDirections	支持的排序方式，取值为 'ascend' 'descend'
// showSorterTooltip	表头是否显示下一次排序的 tooltip 提示

interface DataTableState {
  /** 表格是否加载中 */
  loading: boolean;
  /** 化本地数据(客户端数据) */
  localDataSource?: TableRowData[];
  /** 表格数据 */
  dataSource: TableRowData[];
  /** 分页器配置 */
  pagination: false | TablePaginationConfig;
  /** 当前排序状态 */
  sortOrderColumns: { [column: string]: SortOrder };
  /** 表格当前选中行数据key */
  selectedRowKeys: TableRowSelection<TableRowData>['selectedRowKeys'];
}

class DataTable extends React.Component<DataTableProps, DataTableState> {
  /** 获取对话框默认值 */
  private static getDefaultModalDialogProps(method: ModalDialogProps['method']): Partial<ModalFuncProps> {
    let defaultProps: Partial<ModalFuncProps> = {};
    // TODO 国际化
    switch (method) {
      case 'info':
        defaultProps = { title: '提示' };
        break;
      case 'success':
        defaultProps = { title: '成功' };
        break;
      case 'error':
        defaultProps = { title: '错误' };
        break;
      case 'warning':
        defaultProps = { title: '警告' };
        break;
      case 'confirm':
        defaultProps = { title: '确认', icon: <QuestionCircleOutlined style={{ color: '#faad14' }} /> };
        break;
    }
    return defaultProps;
  }

  /** 获取范围值 */
  private static getRangeValue(val: any): { start: any; end: any } {
    let start: any;
    let end: any;
    if (hasValue(val)) {
      if (variableTypeOf(val) === TypeEnum.array) {
        start = val.length >= 1 ? val[0] : undefined;
        end = val.length >= 2 ? val[1] : undefined;
      } else {
        start = val;
      }
    }
    return { start, end };
  }

  /** 获取文本值 */
  private static getRenderText(val: any): string {
    const type: TypeEnum = variableTypeOf(val);
    if (TypeEnum.string === type) {
      return val;
    } else if (TypeEnum.number === type || TypeEnum.boolean === type) {
      return lodash.toString(val);
    } else if (TypeEnum.array === type) {
      return lodash.trim((val as Array<string>).map((item) => DataTable.getRenderText(item)).join(' '));
    } else if (TypeEnum.date === type) {
      return dateToStr(val as Date);
    }
    return '';
  }

  /** 列排序和操作项排序函数 */
  private static orderCompare(a: any, b: any): number {
    const aInt = hasValue(a?.order) ? a?.order : Number.MIN_VALUE;
    const bInt = hasValue(b?.order) ? b?.order : Number.MIN_VALUE;
    const res = aInt - bInt;
    return res > 0 ? 1 : res < 0 ? -1 : 0;
  }

  static defaultProps: Readonly<Partial<DataTableProps>> = {
    initPagination: false,
    indexColumn: true,
    formatter: {
      number: undefined,
      money: '0,0.00',
      date: 'YYYY-MM-DD',
      datetime: 'YYYY-MM-DD HH:mm:ss',
      time: 'HH:mm:ss',
      timeBeforeFmt: {
        level: 3,
        maxTimeStamp: 7 * 24 * 60 * 60 * 1000,
        // TODO 国际化
        timeUnit: ['年', '个月', '天', '小时', '分钟', '秒'],
      },
      howLongTimeFmt: {
        level: 3,
        timeUnit: ['Y', 'M', 'D', 'h', 'm', 's', 'ms'],
      },
    },
    columns: [],
    columnActions: [],
    columnActionWidth: 120,
    maxActionItem: 2,
    size: 'middle',
    bordered: true,
  };

  /** 表格当前选中行数据 */
  protected selectedRows: TableRowData[] = [];

  constructor(props: DataTableProps) {
    super(props);
    const { initLocalDataSource, columns } = props;
    let { initPagination } = props;
    if (initPagination !== false) {
      if (initPagination === true) initPagination = {};
      initPagination = { ...TableDefaultPagination, ...initPagination };
    }
    const sortOrderColumns: ReloadParams['sortOrderColumns'] = {};
    if (columns) {
      columns.forEach((column) => {
        if (column.sortOrder && variableTypeOf(column.sortOrder) === TypeEnum.string && column.dataIndex) {
          if (variableTypeOf(column.dataIndex) === TypeEnum.array) {
            sortOrderColumns[(column.dataIndex as string[]).join('.')] = column.sortOrder ?? 'ascend';
          } else {
            sortOrderColumns[column.dataIndex as string] = column.sortOrder ?? 'ascend';
          }
        }
      });
    }
    this.state = {
      loading: false,
      localDataSource: initLocalDataSource,
      dataSource: [],
      pagination: initPagination,
      sortOrderColumns,
      selectedRowKeys: [],
    };
    if (initLocalDataSource) {
      // 初始化客户端数据
      const pageNo = TableDefaultPagination.current ?? TableDefaultPagination.defaultCurrent;
      const pageSize = TableDefaultPagination.pageSize ?? TableDefaultPagination.defaultPageSize;
      const res = this.reloadByClient(pageNo!, pageSize!, sortOrderColumns);
      const newState: Partial<DataTableState> = this.state;
      newState.dataSource = res.dataSource;
      if (newState.pagination) {
        newState.pagination.total = res.total;
        if (res.current) newState.pagination.current = res.current;
        if (res.pageSize) newState.pagination.pageSize = res.pageSize;
      }
      this.state = newState as Readonly<DataTableState>;
    }
  }

  async componentDidMount() {
    const { serverPaginationData, serverData } = this.props;
    if (serverPaginationData && (serverPaginationData.initLoadData ?? ServerTableDataDefaultConfig.initLoadData)) {
      await this.reload({ model: ReloadModel.Keep });
    } else if (serverData && (serverData.initLoadData ?? ServerDataDefaultConfig.initLoadData)) {
      await this.reloadServerData(true);
    }
  }

  /** 数字格式化 */
  protected numberFormatter(num: number, fmt?: string): ReactNode {
    const { formatter } = this.props;
    if (fmt) return numberFormat(num, fmt);
    if (formatter && formatter.number) {
      if (formatter.number instanceof Function) return formatter.number(num);
      return numberFormat(num, formatter.number);
    }
    return num;
  }

  /** 金额格式化 */
  protected moneyFormatter(money: number, fmt?: string): ReactNode {
    const { formatter } = this.props;
    if (fmt) return numberFormat(money, fmt);
    if (formatter && formatter.money) {
      if (formatter.money instanceof Function) return formatter.money(money);
      return numberFormat(money, formatter.money);
    }
    return money;
  }

  /** 日期格式化 */
  protected dateFormatter(date: Date, fmt?: string): ReactNode {
    const { formatter } = this.props;
    if (fmt) return dateToStr(date, fmt);
    if (formatter && formatter.date) {
      if (formatter.date instanceof Function) return formatter.date(date);
      return dateToStr(date, formatter.date);
    }
    return date;
  }

  /** 日期时间格式化 */
  protected datetimeFormatter(datetime: Date, fmt?: string): ReactNode {
    const { formatter } = this.props;
    if (fmt) return dateToStr(datetime, fmt);
    if (formatter && formatter.datetime) {
      if (formatter.datetime instanceof Function) return formatter.datetime(datetime);
      return dateToStr(datetime, formatter.datetime);
    }
    return datetime;
  }

  /** 时间格式化 */
  protected timeFormatter(time: Date, fmt?: string): ReactNode {
    const { formatter } = this.props;
    if (fmt) return dateToStr(time, fmt);
    if (formatter && formatter.time) {
      if (formatter.time instanceof Function) return formatter.time(time);
      return dateToStr(time, formatter.time);
    }
    return time;
  }

  /** TimeBefore格式化 */
  protected timeBeforeFormatter(agoDate: Date, fmt?: TableColumn['timeBeforeFmt']): ReactNode {
    const { formatter } = this.props;
    const useFmt = fmt ?? (formatter && formatter.timeBeforeFmt ? formatter.timeBeforeFmt : {});
    return howLongAgo(agoDate, useFmt.level, useFmt.maxTimeStamp, useFmt.timeUnit);
  }

  /** HowLongTime格式化 */
  protected howLongTimeFormatter(time: number, fmt?: TableColumn['howLongTimeFmt']): ReactNode {
    const { formatter } = this.props;
    const useFmt = fmt ?? (formatter && formatter.howLongTimeFmt ? formatter.howLongTimeFmt : {});
    return howLong(time, useFmt.level, useFmt.timeUnit);
  }

  /** 数据大小格式化 */
  protected dataBytesSizeFormatter(num: number): ReactNode {
    return bytesFormat(num);
  }

  /** 获取组件属性值 */
  protected getPropsItem(originalValue: any, value: any, record: TableRowData, getProps: any): BasePropsItem {
    let props: any = { value, label: '未知' };
    if (getProps) {
      if (getProps instanceof Function) {
        props = getProps(originalValue, value, record);
      } else if (variableTypeOf(getProps) === TypeEnum.array) {
        props = getMapperDataItem(getProps, originalValue);
      }
    }
    return props;
  }

  /** 获取序号列 */
  protected getIndexColumn(): ColumnProps<TableRowData> | false {
    const { dataSource, pagination } = this.state;
    const { indexColumn } = this.props;
    // console.log("pagination", pagination)
    // TODO 国际化
    const indexCol: ColumnProps<TableRowData> = { key: 'default_index_column', sorter: false, title: '序号', width: 60, align: 'center' };
    let addIndexCol = false;
    let startIndexTmp = 1;
    if (variableTypeOf(pagination) === TypeEnum.object && (pagination as TablePaginationConfig).pageSize && (pagination as TablePaginationConfig).current) {
      let current = lodash.toNumber((pagination as TablePaginationConfig).current) - 1;
      if (current < 0) current = 0;
      startIndexTmp = current * lodash.toNumber((pagination as TablePaginationConfig).pageSize) + 1;
    }
    const startIndex = startIndexTmp;
    const endIndex = startIndexTmp + dataSource.length - 1;
    indexCol.width = `${endIndex}`.length * 8 + 3;
    if (indexCol.width < 50) indexCol.width = 50;
    if (indexColumn === true) {
      addIndexCol = true;
      // console.log("startIndex = ", startIndex, endIndex);
      indexCol.render = (): React.ReactNode => {
        const res = startIndexTmp++;
        if (startIndexTmp > endIndex) startIndexTmp = startIndex;
        return res;
      };
    } else if (indexColumn instanceof Function) {
      addIndexCol = true;
      indexCol.render = (value: any, record: TableRowData): React.ReactNode => {
        const res = startIndexTmp++;
        if (startIndexTmp > endIndex) startIndexTmp = startIndex;
        return indexColumn(res, record);
      };
    }
    return addIndexCol ? indexCol : false;
  }

  /** 获取数据列 */
  protected getTableColumn(tableColumn: TableColumn): ColumnProps<TableRowData> {
    const { sortOrderColumns } = this.state;
    const sortOrder: SortOrder =
      sortOrderColumns[variableTypeOf(tableColumn?.dataIndex) === TypeEnum.array ? (tableColumn?.dataIndex as Array<string>)?.join('.') : (tableColumn?.dataIndex as string) || ''];
    const {
      renderText,
      valueType,
      formatter,
      timeBeforeFmt,
      howLongTimeFmt,
      mapperData,
      wrapperType,
      getAvatarProps,
      getBadgeProps,
      getPopoverProps,
      getTooltipProps,
      getTagProps,
      getProgressProps,
      getPopConfirmProps,
      getLinkProps,
      getModalDialogProps,
      getCheckboxProps,
      getCheckboxGroupProps,
      getRateProps,
      getRadioProps,
      getRadioGroupProps,
      getSwitchProps,
      getSliderProps,
      prefix,
      suffix,
      ...colProps
    } = tableColumn;
    // if (sortOrder) colProps.sorter = true;
    const col: ColumnProps<TableRowData> = { ...colProps, sortOrder };
    // 需要自定义 render
    if ((hasValue(valueType) || hasValue(wrapperType) || hasValue(prefix) || hasValue(suffix)) && !col.render) {
      col.render = (value: any, record: TableRowData, index: number): React.ReactNode => {
        // 数据值处理(格式化)
        let val: any = value;
        switch (valueType) {
          case DataValueType.Number:
            val = lodash.toNumber(val);
            val = this.numberFormatter(val, formatter);
            break;
          case DataValueType.Money:
            val = lodash.toNumber(val);
            val = this.moneyFormatter(val, formatter);
            break;
          case DataValueType.Date:
            const dateVal = toDayjs(val);
            if (!dateVal || !dateVal.isValid()) break;
            val = dateVal.toDate();
            val = this.dateFormatter(val, formatter);
            break;
          case DataValueType.DateTime:
            const dateTimeVal = toDayjs(val);
            if (!dateTimeVal || !dateTimeVal.isValid()) break;
            val = dateTimeVal.toDate();
            val = this.datetimeFormatter(val, formatter);
            break;
          case DataValueType.Time:
            const timeVal = toDayjs(val);
            if (!timeVal || !timeVal.isValid()) break;
            val = timeVal.toDate();
            val = this.timeFormatter(val, formatter);
            break;
          case DataValueType.DateRange:
            let { start: startDate, end: endDate } = DataTable.getRangeValue(val);
            const startDateVal = toDayjs(startDate);
            const endDateVal = toDayjs(endDate);
            if (startDateVal && startDateVal.isValid()) {
              startDate = startDateVal.toDate();
              startDate = this.dateFormatter(startDate, formatter);
            }
            if (endDateVal && endDateVal.isValid()) {
              endDate = endDateVal.toDate();
              endDate = this.dateFormatter(endDate, formatter);
            }
            if (startDate || endDate) {
              val = `${startDate ?? '?'} ~ ${endDate ?? '?'}`;
            } else {
              val = '-';
            }
            break;
          case DataValueType.DateTimeRange:
            let { start: startTime, end: endTime } = DataTable.getRangeValue(val);
            const startTimeVal = toDayjs(startTime);
            const endTimeVal = toDayjs(endTime);
            if (startTimeVal && startTimeVal.isValid()) {
              startTime = startTimeVal.toDate();
              startTime = this.datetimeFormatter(startTime, formatter);
            }
            if (endTimeVal && endTimeVal.isValid()) {
              endTime = endTimeVal.toDate();
              endTime = this.datetimeFormatter(endTime, formatter);
            }
            if (startTime || endTime) {
              val = `${startTime ?? '?'} ~ ${endTime ?? '?'}`;
            } else {
              val = '-';
            }
            break;
          case DataValueType.TimeBefore:
            // "Date(时间字符串)" | "数字(数字字符串)"
            if (hasValue(value) && variableTypeOf(val) !== TypeEnum.date && variableTypeOf(lodash.toNumber(val)) === TypeEnum.number) {
              const time = lodash.toNumber(val);
              const agoDate = dateSubtract(time, 'millisecond').toDate();
              val = this.timeBeforeFormatter(agoDate, timeBeforeFmt);
            } else {
              const dayjsTmp = toDayjs(val);
              if (dayjsTmp && dayjsTmp.isValid()) {
                const agoDate: Date = dayjsTmp.toDate();
                val = this.timeBeforeFormatter(agoDate, timeBeforeFmt);
              }
            }
            if (!hasValue(val)) val = '-';
            break;
          case DataValueType.HowLongTime:
            // "Date(时间字符串)" | "数字(数字字符串)"
            if (hasValue(value) && variableTypeOf(val) !== TypeEnum.date && variableTypeOf(lodash.toNumber(val)) === TypeEnum.number) {
              const time = lodash.toNumber(val);
              val = this.howLongTimeFormatter(time, howLongTimeFmt);
            } else {
              const dayjsTmp = toDayjs(val);
              if (dayjsTmp && dayjsTmp.isValid()) {
                const date: Date = dayjsTmp.toDate();
                const time = new Date().getTime() - date.getTime();
                // time = time >= 0 ? time : time * -1;
                val = this.howLongTimeFormatter(time, howLongTimeFmt);
              }
            }
            if (!hasValue(val)) val = '-';
            break;
          case DataValueType.DataBytesSize:
            val = lodash.toNumber(val);
            val = this.dataBytesSizeFormatter(val);
            break;
        }
        // 搜索使用的文本
        let internalSearchText = val;
        // 数据显示UI组件包装
        switch (wrapperType) {
          case DataWrapperType.Mapper:
            const item: EnumArrayItem = getMapperDataItem(mapperData ?? [], val);
            if (hasValue(item.customLabel)) {
              val = item.customLabel;
            } else if (hasValue(item.style)) {
              val = <span style={{ display: 'inline-block', ...item.style }}>{item.label}</span>;
            } else if (hasValue(item.label)) {
              val = item.label;
            } else {
              val = item.value;
            }
            internalSearchText = item.value;
            break;
          case DataWrapperType.Avatar:
            const avatarProps: AvatarProps = {
              size: 'small',
              children: val,
              ...this.getPropsItem(value, val, record, getAvatarProps),
            };
            val = <Avatar {...avatarProps} />;
            internalSearchText = DataTable.getRenderText(avatarProps.children);
            break;
          case DataWrapperType.Badge:
            const badgeProps: BadgeProps = {
              status: 'default',
              text: val,
              ...this.getPropsItem(value, val, record, getBadgeProps),
            };
            val = <Badge {...badgeProps} />;
            internalSearchText = DataTable.getRenderText(badgeProps.text);
            break;
          case DataWrapperType.Popover:
            const popoverProps: PopoverProps = {
              content: val,
              children: <a>详情</a>,
              ...this.getPropsItem(value, val, record, getPopoverProps),
            } as PopoverProps;
            val = <Popover {...popoverProps} />;
            internalSearchText = '';
            break;
          case DataWrapperType.Tooltip:
            const tooltipProps: TooltipProps = {
              title: val,
              children: <span>详情</span>,
              ...this.getPropsItem(value, val, record, getTooltipProps),
            } as TooltipProps;
            val = <Tooltip {...tooltipProps} />;
            internalSearchText = '';
            break;
          case DataWrapperType.Tag:
            const { children, ...baseProps } = this.getPropsItem(value, val, record, getTagProps) as any;
            if (variableTypeOf(children) === TypeEnum.array) {
              val = [];
              (children as Array<any>).forEach((tag, idx) =>
                val.push(
                  <Tag key={idx} color="default" {...baseProps}>
                    {tag}
                  </Tag>,
                ),
              );
            } else {
              const tagProps: TagProps = { color: 'default', children: children ?? val, ...baseProps } as TagProps;
              val = <Tag {...tagProps} />;
            }
            internalSearchText = DataTable.getRenderText(children);
            break;
          case DataWrapperType.Progress:
            const progressProps: ProgressProps = {
              size: 'small',
              percent: variableTypeOf(lodash.toNumber(val)) === TypeEnum.number ? lodash.toNumber(val) : 0,
              ...this.getPropsItem(value, val, record, getProgressProps),
            } as ProgressProps;
            val = <Progress {...progressProps} />;
            internalSearchText = DataTable.getRenderText(progressProps.percent);
            break;
          case DataWrapperType.PopConfirm:
            const popConfirmProps: PopconfirmProps = {
              title: '继续当前操作?',
              children: <a>操作</a>,
              ...this.getPropsItem(value, val, record, getPopConfirmProps),
            } as PopconfirmProps;
            val = <Popconfirm {...popConfirmProps} />;
            internalSearchText = '';
            break;
          case DataWrapperType.Link:
            const link = val;
            const linkProps: LinkProps<any> = {
              children: link,
              to: {},
              ...this.getPropsItem(value, val, record, getLinkProps),
            } as LinkProps<any>;
            val = <UmiLink {...linkProps} />;
            internalSearchText = DataTable.getRenderText(linkProps.children);
            break;
          case DataWrapperType.ModalDialog:
            const content = val;
            const modalDialogProps: ModalDialogProps = {
              method: 'info',
              content,
              children: '查看',
              ...this.getPropsItem(value, val, record, getModalDialogProps),
            } as ModalDialogProps;
            if (modalDialogProps.method && Modal[modalDialogProps.method]) {
              val = (
                <a onClick={() => Modal[modalDialogProps.method]({ ...DataTable.getDefaultModalDialogProps(modalDialogProps.method), ...modalDialogProps })}>
                  {(modalDialogProps as any)?.children}
                </a>
              );
              internalSearchText = '';
            }
            break;
          case DataWrapperType.Checkbox:
            const { value: _1, label: label1, ...propsTmp } = this.getPropsItem(value, val, record, getCheckboxProps);
            const checkboxProps: CheckboxProps = { children: val ?? label1, defaultChecked: !!label1, ...propsTmp };
            val = <Checkbox {...checkboxProps} />;
            break;
          case DataWrapperType.CheckboxGroup:
            const options = val instanceof Array ? val : value instanceof Array ? value : [];
            if (getCheckboxGroupProps instanceof Function) {
              const { value: _6, label: label6, ...propsTmp6 } = this.getPropsItem(value, val, record, getCheckboxGroupProps);
              const checkboxGroupProps: CheckboxGroupProps = { defaultValue: options, ...propsTmp6 };
              val = <Checkbox.Group {...checkboxGroupProps} />;
            } else if (options.length > 0) {
              if (variableTypeOf(options[0]) === TypeEnum.object) {
                val = <Checkbox.Group options={options} defaultValue={options.map((itm) => itm.value).filter((itm) => itm)} />;
              } else {
                const optionsTmp = options.filter((itm) => hasValue(itm)).map((itm) => lodash.toString(itm));
                val = <Checkbox.Group options={optionsTmp} defaultValue={optionsTmp} />;
              }
            } else if (getCheckboxGroupProps instanceof Array) {
              const { value: _6, label: label6, ...propsTmp6 } = this.getPropsItem(value, val, record, getCheckboxGroupProps);
              if (!(propsTmp6 as CheckboxGroupProps).options) {
                const optionsTmp = [lodash.toString(val)];
                (propsTmp6 as CheckboxGroupProps).options = optionsTmp;
                (propsTmp6 as CheckboxGroupProps).defaultValue = optionsTmp;
              }
              const checkboxGroupProps: CheckboxGroupProps = { defaultValue: options, ...propsTmp6 };
              val = <Checkbox.Group {...checkboxGroupProps} />;
            } else {
              const optionsTmp = [lodash.toString(val)];
              val = <Checkbox.Group options={optionsTmp} defaultValue={optionsTmp} />;
            }
            internalSearchText = '';
            break;
          case DataWrapperType.Rate:
            const { value: _2, label: label2, ...propsTmp2 } = this.getPropsItem(value, val, record, getRateProps);
            const rateProps: RateProps = { defaultValue: variableTypeOf(label2) === TypeEnum.number ? label2 : _2, ...propsTmp2 } as RateProps;
            val = <Rate {...rateProps} />;
            internalSearchText = '';
            break;
          case DataWrapperType.Radio:
            const { value: _3, label: label3, ...propsTmp3 } = this.getPropsItem(value, val, record, getRadioProps);
            const radioProps: RadioProps = { children: val, defaultChecked: !!label3, ...propsTmp3 };
            val = <Radio {...radioProps} />;
            break;
          case DataWrapperType.RadioGroup:
            const options2 = val instanceof Array ? val : value instanceof Array ? value : [];
            if (getRadioGroupProps instanceof Function) {
              const { value: _7, label: label7, ...propsTmp7 } = this.getPropsItem(value, val, record, getRadioGroupProps);
              const radioGroupProps: RadioGroupProps = { defaultValue: options2[0], ...propsTmp7 };
              val = <Radio.Group {...radioGroupProps} />;
            } else if (options2.length > 0) {
              if (variableTypeOf(options2[0]) === TypeEnum.object) {
                val = <Radio.Group options={options2} defaultValue={options2.map((itm) => itm.value).filter((itm) => itm)[0]} />;
              } else {
                const optionsTmp = options2.filter((itm) => hasValue(itm)).map((itm) => lodash.toString(itm));
                val = <Radio.Group options={optionsTmp} defaultValue={optionsTmp[0]} />;
              }
            } else if (getRadioGroupProps instanceof Array) {
              const { value: _7, label: label7, ...propsTmp7 } = this.getPropsItem(value, val, record, getRadioGroupProps);
              if (!(propsTmp7 as RadioGroupProps).options) {
                const optionsTmp = [lodash.toString(val)];
                (propsTmp7 as CheckboxGroupProps).options = optionsTmp;
                (propsTmp7 as CheckboxGroupProps).defaultValue = optionsTmp;
              }
              const radioGroupProps: RadioGroupProps = { defaultValue: options2[0], ...propsTmp7 };
              val = <Radio.Group {...radioGroupProps} />;
            } else {
              const optionsTmp = [lodash.toString(val)];
              val = <Radio.Group options={optionsTmp} defaultValue={optionsTmp[0]} />;
            }
            internalSearchText = '';
            break;
          case DataWrapperType.Switch:
            const { value: _4, label: label4, ...propsTmp4 } = this.getPropsItem(value, val, record, getSwitchProps);
            const switchProps: SwitchProps = { size: 'small', defaultChecked: !!label4, ...propsTmp4 };
            val = <Switch {...switchProps} />;
            internalSearchText = '';
            break;
          case DataWrapperType.Slider:
            const { value: _5, label: label5, ...propsTmp5 } = this.getPropsItem(value, val, record, getSliderProps);
            const sliderProps: AntdSliderProps = { defaultValue: (variableTypeOf(label5) === TypeEnum.number ? label5 : _5) as number, ...propsTmp5 };
            val = <Slider {...sliderProps} />;
            internalSearchText = '';
            break;
        }
        // 数据过滤文本处理
        if (!hasValue(record.__internalSearchText)) {
          if (renderText instanceof Function) {
            record.__internalSearchText = renderText(value, val);
          } else {
            record.__internalSearchText = lodash.toString(internalSearchText);
          }
        }
        const prefixNode = prefix instanceof Function ? prefix(value, val, record, this) : prefix;
        const suffixNode = suffix instanceof Function ? suffix(value, val, record, this) : suffix;
        return (
          <>
            {prefixNode}
            {val}
            {suffixNode}
          </>
        );
      };
    }
    return col;
  }

  /** 获取操作列 */
  protected getTableColumnAction(columnActions: TableColumnAction[]): ColumnProps<TableRowData> {
    const { columnActionWidth, maxActionItem, moreActionButton } = this.props;
    const col: ColumnProps<TableRowData> = { key: 'default_action_column', sorter: false, title: '操作', width: columnActionWidth ?? 120, align: 'center' };
    // 操作处理逻辑包装
    const onActionWrap = async (event: any, record: TableRowData, actionType?: ActionType, onAction?: TableColumnAction['onAction'], modalDialogProps?: ModalDialogProps) => {
      // 完全自定义处理操作项触发逻辑
      if (onAction instanceof Function) await onAction(record, this, event);
      if (actionType === ActionType.ModalDialog && modalDialogProps && Modal[modalDialogProps.method] instanceof Function) {
        const defaultProps: Partial<ModalFuncProps> = DataTable.getDefaultModalDialogProps(modalDialogProps.method);
        Modal[modalDialogProps.method]({ ...defaultProps, ...modalDialogProps });
      }
    };
    col.render = (value: any, record: TableRowData, index: number): ReactNode => {
      const renderNode: Array<any> = [];
      const moreNode: Array<any> = [];
      columnActions.sort(DataTable.orderCompare).forEach((action, idx) => {
        const { actionStyle, actionExtProps, appendDivider, actionType, getLinkProps, getModalDialogProps, getPopConfirmProps, onCancel, onConfirm, onAction } = action;
        const actionIcon: ReactNode = action.actionIcon instanceof Function ? action.actionIcon(record) : action.actionIcon;
        const actionText: ReactNode = action.actionText instanceof Function ? action.actionText(record) : action.actionText;
        // 获取各种包装组件属性
        let linkProps: LinkProps<any> = {} as LinkProps<any>;
        let modalDialogProps: ModalDialogProps = {} as ModalDialogProps;
        let popConfirmProps: PopconfirmProps = {} as PopconfirmProps;
        let onCancelTmp: any;
        let onConfirmTmp: any;
        switch (actionType) {
          // 气泡确认框交互
          case ActionType.Link:
            linkProps = (getLinkProps instanceof Function ? getLinkProps(record, this) : getLinkProps) as LinkProps<any>;
            break;
          // 弹出对话框
          case ActionType.ModalDialog:
            modalDialogProps = { content: '确认执行?', ...(getModalDialogProps instanceof Function ? getModalDialogProps(record, this) : getModalDialogProps) } as ModalDialogProps;
            onCancelTmp = modalDialogProps.onCancel;
            onConfirmTmp = modalDialogProps.onOk;
            modalDialogProps.onCancel = async (event) => {
              if (onCancelTmp instanceof Function) await onCancelTmp(event);
              if (onCancel instanceof Function) await onCancel(record, this, event);
            };
            modalDialogProps.onOk = async (event) => {
              if (onConfirmTmp instanceof Function) await onConfirmTmp(event);
              if (onConfirm instanceof Function) await onConfirm(record, this, event);
            };
            break;
          // 气泡确认框交互
          case ActionType.PopConfirm:
            popConfirmProps = (getPopConfirmProps instanceof Function ? getPopConfirmProps(record, this) : getPopConfirmProps ?? {}) as PopconfirmProps;
            onCancelTmp = popConfirmProps.onCancel;
            onConfirmTmp = popConfirmProps.onConfirm;
            popConfirmProps.onCancel = async (event) => {
              if (onCancelTmp instanceof Function) await onCancelTmp(event);
              if (onCancel instanceof Function) await onCancel(record, this, event);
            };
            popConfirmProps.onConfirm = async (event) => {
              if (onConfirmTmp instanceof Function) await onConfirmTmp(event);
              if (onConfirm instanceof Function) await onConfirm(record, this, event);
            };
            break;
        }
        // 原始操作项内容
        let actionNode: any;
        // 分隔条
        let divider: any;
        // 包装操作项组件
        // let actionNodeWrap: any;
        // 当前操作项是否是“更多”菜单项
        const isMoreItem = maxActionItem && idx >= maxActionItem;
        if (isMoreItem) {
          // 更多-菜单项
          actionNode = (
            <Menu.Item
              key={idx}
              icon={actionIcon}
              style={actionStyle}
              {...actionExtProps}
              onClick={async (param) => {
                await onActionWrap(param, record, actionType, onAction, modalDialogProps);
              }}
            >
              {actionType === ActionType.Link ? <UmiLink {...linkProps}>{actionText}</UmiLink> : actionText}
            </Menu.Item>
          );
        } else if (actionType === ActionType.Link) {
          // 跳转链接
          actionNode = (
            <UmiLink
              key={idx}
              style={{ whiteSpace: 'nowrap', ...actionStyle }}
              {...actionExtProps}
              onClick={async (event) => {
                await onActionWrap(event, record, actionType, onAction, modalDialogProps);
              }}
              {...linkProps}
            >
              {actionIcon} {actionText}
            </UmiLink>
          );
        } else if (actionType === ActionType.PopConfirm) {
          // 气泡确认框交互
          actionNode = (
            // TODO 国际化
            <Popconfirm key={idx} title={'提示'} trigger={'click'} {...popConfirmProps}>
              <a
                key={idx}
                style={{ whiteSpace: 'nowrap', ...actionStyle }}
                {...actionExtProps}
                onClick={async (event) => {
                  await onActionWrap(event, record, actionType, onAction, modalDialogProps);
                }}
              >
                {actionIcon} {actionText}
              </a>
            </Popconfirm>
          );
        } else {
          //  直接显示的操作项
          actionNode = (
            <a
              key={idx}
              style={{ whiteSpace: 'nowrap', ...actionStyle }}
              {...actionExtProps}
              onClick={async (event) => {
                await onActionWrap(event, record, actionType, onAction, modalDialogProps);
              }}
            >
              {actionIcon} {actionText}
            </a>
          );
        }
        // 需要追加分隔条
        if (appendDivider) {
          if (isMoreItem) {
            divider = <Menu.Divider key={`${idx}-divider`} />;
          } else {
            divider = <Divider key={`${idx}-divider`} type={'vertical'} style={{ margin: '0 4px' }} />;
          }
        }
        // push 操作项
        const container = isMoreItem ? moreNode : renderNode;
        container.push(actionNode);
        if (divider) {
          container.push(divider);
        }
      });
      if (moreNode.length >= 1) {
        const moreActionNode: ReactNode = moreActionButton ?? <EllipsisOutlined style={{ cursor: 'pointer', color: '#1890ff' }} />;
        renderNode.push(
          <Dropdown key={'more-actions'} overlay={<Menu>{moreNode}</Menu>} trigger={['hover']}>
            {moreActionNode}
          </Dropdown>,
        );
      }
      return (
        <Space align={'center'} direction={'horizontal'} size={8}>
          {renderNode}
        </Space>
      );
    };
    return col;
  }

  /** 获取表格列 */
  protected getColumns(): ColumnProps<TableRowData>[] {
    const { columns, columnActions } = this.props;
    const cols: ColumnProps<TableRowData>[] = [];
    const tableCols: ColumnProps<TableRowData>[] = [];
    let actionCol: ColumnProps<TableRowData> | null = null;
    // 设置序号列
    const indexCol = this.getIndexColumn();
    // 获取数据列
    if (columns && columns.length > 0) columns.forEach((tableColumn) => tableCols.push(this.getTableColumn(tableColumn)));
    // 获取操作列
    if (columnActions && columnActions.length > 0) actionCol = this.getTableColumnAction(columnActions);
    // 组装表格列
    if (indexCol) cols.push(indexCol);
    if (tableCols.length > 0) tableCols.sort(DataTable.orderCompare).forEach((col) => cols.push(col));
    if (actionCol) cols.push(actionCol);
    // console.log("columns", cols)
    return cols;
  }

  /** 获取表格行选择配置 */
  protected getRowSelection(): null | Partial<TableRowSelection<TableRowData>> {
    const { selectionMode, rowSelection } = this.props;
    const { selectedRowKeys } = this.state;
    if (!selectionMode) return null;
    const resRowSelection: Partial<TableRowSelection<TableRowData>> = {
      type: selectionMode,
      columnWidth: 50,
      selections: false,
      selectedRowKeys,
      onChange: (keys, rows) => {
        // console.log("selectedRowKeys", selectedRowKeys);
        this.selectedRows = rows;
        this.setState({ selectedRowKeys: keys });
      },
    };
    switch (selectionMode) {
      case 'checkbox':
        break;
      case 'radio':
        // TODO 国际化
        resRowSelection.columnTitle = '选择';
        break;
    }
    return { ...resRowSelection, ...rowSelection };
  }

  /** 获取数据表格 */
  protected getDataTable() {
    const { rowKey, size, bordered, tableProps } = this.props;
    const { loading, dataSource, pagination } = this.state;
    const dynamicTableProps: Partial<TableProps<TableRowData>> = {};
    const rowSelection = this.getRowSelection();
    if (rowSelection) dynamicTableProps.rowSelection = rowSelection;
    // console.log("pagination", pagination);
    return (
      <Table
        size={size}
        bordered={bordered}
        columns={this.getColumns()}
        rowKey={rowKey}
        loading={loading}
        dataSource={dataSource}
        pagination={pagination}
        onChange={async (pageInfo, filters, sorter, extra) => {
          const reloadParams: ReloadParams = { model: ReloadModel.Pagination };
          // 分页参数
          if (pageInfo) {
            reloadParams.pageSize = pageInfo.pageSize;
            reloadParams.pageNo = pageInfo.current;
          }
          // 排序参数
          if (sorter) {
            reloadParams.sortOrderColumns = {};
            if (variableTypeOf(sorter) === TypeEnum.array) {
              const sorterResultArray: SorterResult<TableRowData>[] = sorter as SorterResult<TableRowData>[];
              sorterResultArray.forEach((sorterResult) => {
                if (!sorterResult?.order) return;
                const field: string = variableTypeOf(sorterResult.field) === TypeEnum.array ? (sorterResult?.field as Array<string>)?.join('.') : (sorterResult.field as string);
                reloadParams.sortOrderColumns![field] = sorterResult?.order;
              });
            } else {
              const sorterResult: SorterResult<TableRowData> = sorter as SorterResult<TableRowData>;
              if (sorterResult?.order) {
                const field: string = variableTypeOf(sorterResult.field) === TypeEnum.array ? (sorterResult?.field as Array<string>)?.join('.') : (sorterResult.field as string);
                reloadParams.sortOrderColumns[field] = sorterResult?.order;
              }
            }
          }
          // 客户端/服务端 - reload
          await this.reload(reloadParams);
        }}
        {...dynamicTableProps}
        {...tableProps}
      />
    );
  }

  public render() {
    // console.log("render");
    return this.getDataTable();
  }

  // -------------------------------------------------------------------------------------------------------------- 外部方法

  /**
   * 当前是否是正在加载中
   */
  public isLoading(): boolean {
    return this.state.loading;
  }

  /**
   * 设置当前组件加载中状态
   */
  public setLoading(loading: boolean): void {
    const { loading: oldLoading } = this.state;
    const { onLoadingChange } = this.props;
    if (oldLoading !== loading && onLoadingChange instanceof Function) onLoadingChange(loading);
    this.setState({ loading });
  }

  /**
   * 重新加载当前页数据(刷新数据)
   */
  public async refresh(): Promise<void> {
    await this.reload({ model: ReloadModel.Keep });
  }

  /**
   * 重新加载页面数据(远程数据或者客户端数据)
   */
  public async reload(params: ReloadParams): Promise<void> {
    const { pagination } = this.state;
    // 不分页-不需要reload
    if (pagination === false) return;
    // 计算 pageNo、pageSize、sortOrderColumns
    const { model } = params;
    let { pageSize, pageNo, sortOrderColumns } = params;
    if (!sortOrderColumns) sortOrderColumns = this.state.sortOrderColumns;
    switch (model) {
      case ReloadModel.ToFirst:
        // 跳转到第一页
        pageNo = 1;
        if (pagination?.pageSize) pageSize = pagination?.pageSize;
        break;
      case ReloadModel.Keep:
        // 保持当前页
        if (pagination?.current) pageNo = pagination?.current;
        if (pagination?.pageSize) pageSize = pagination?.pageSize;
        break;
      case ReloadModel.Pagination:
        // 改变分页
        pageNo = pageNo ?? pagination?.current;
        pageSize = pageSize ?? pagination?.pageSize;
        break;
    }
    // 重新加载数据
    const { serverPaginationData } = this.props;
    if (serverPaginationData) {
      // 加载远程数据
      await this.reloadByRemote(pageNo!, pageSize!, sortOrderColumns);
    } else {
      // 加载客户端数据
      const res = this.reloadByClient(pageNo!, pageSize!, sortOrderColumns);
      res.updateState();
    }
  }

  /**
   * 加载远程数据
   * @param pageNo            当前页
   * @param pageSize          页大小
   * @param sortOrderColumns  排序方式
   */
  public async reloadByRemote(pageNo: number, pageSize: number, sortOrderColumns: ReloadParams['sortOrderColumns']): Promise<void> {
    let { serverPaginationData } = this.props;
    if (!serverPaginationData) return;
    // 服务端加载数据配置
    serverPaginationData = { ...ServerTableDataDefaultConfig, ...serverPaginationData };
    const urlParams: any = {};
    // 处理分页参数
    if (serverPaginationData.enablePagination) {
      urlParams[serverPaginationData?.pageNoParamName!] = pageNo;
      urlParams[serverPaginationData?.pageSizeParamName!] = pageSize;
    }
    // 处理排序参数
    if (sortOrderColumns) {
      lodash.forEach(sortOrderColumns, (order, column) => {
        if (!order) return;
        if (!urlParams.orderFields) urlParams.orderFields = [];
        urlParams.orderFields.push(column);
        if (!urlParams.sorts) urlParams.sorts = [];
        urlParams.sorts.push(order === 'ascend' ? 'ASC' : 'DESC');
      });
    }
    serverPaginationData.url = `${serverPaginationData.url}?${stringify(urlParams, { indices: false })}`;
    this.setLoading(true);
    await getServerTableData(serverPaginationData, (data) => {
      if (!data) return;
      const { pagination } = this.state;
      const newState: Partial<DataTableState> = {};
      const { records, current, size, total, orders } = data ?? {};
      // pages searchCount
      newState.dataSource = records ?? [];
      if (variableTypeOf(pagination) === TypeEnum.object) {
        newState.pagination = { ...pagination, total, current, pageSize: size };
      }
      if (orders) {
        newState.sortOrderColumns = {};
        orders.forEach((order) => {
          if (!order || !order.column) return;
          newState.sortOrderColumns![order.column] = order.asc ? 'ascend' : 'descend';
        });
      }
      this.setState(newState as DataTableState);
    }).finally(() => this.setLoading(false));
  }

  /**
   * 加载客户端数据
   * @param pageNo            当前页
   * @param pageSize          页大小
   * @param sortOrderColumns  排序方式
   */
  public reloadByClient(pageNo: number, pageSize: number, sortOrderColumns: ReloadParams['sortOrderColumns']): GetLocalDataSourceRes {
    const { localDataSource, pagination } = this.state;
    let dataSource: TableRowData[] = localDataSource ?? [];
    const total = dataSource.length;
    // 定义返回值
    const updateState = () => {
      const newState: Partial<DataTableState> = { dataSource: res.dataSource, pagination };
      if (newState.pagination) {
        newState.pagination.total = res.total;
        if (res.current) newState.pagination.current = res.current;
        if (res.pageSize) newState.pagination.pageSize = res.pageSize;
      }
      newState.sortOrderColumns = sortOrderColumns;
      this.setState(newState as DataTableState);
    };
    const res: GetLocalDataSourceRes = { dataSource, total, updateState };
    // 排序处理
    if (sortOrderColumns) {
      const fieldsSort: FieldSort[] = [];
      lodash.forEach(sortOrderColumns, (value, field) => {
        if (!value) return;
        fieldsSort.push({ field, by: value === 'descend' ? 'DESC' : 'ASC' });
      });
      if (fieldsSort.length > 0) {
        dataSource = sortDataSet(dataSource, fieldsSort) as TableRowData[];
        // console.log("fieldsSort", fieldsSort)
      }
    }
    // 分页处理
    if (pagination === false) {
      return res;
    }
    let current = pageNo;
    let start = (pageNo - 1) * pageSize;
    let end = pageNo * pageSize;
    if (start >= total) {
      current = Math.ceil(total / pageSize);
      start = (current - 1) * pageSize;
      end = current * pageSize;
    } else if (end > total) {
      end = total;
    }
    dataSource = dataSource.slice(start, end);
    res.dataSource = dataSource;
    res.current = current;
    res.pageSize = pageSize;
    return res;
  }

  /**
   * 加载远程数据(serverData配置，非分页数据)
   * @param refreshTable  加载成功后是否刷新表格当前数据
   */
  public async reloadServerData(refreshTable?: boolean): Promise<void> {
    let { serverData } = this.props;
    if (!serverData) return;
    serverData = { ...ServerDataDefaultConfig, ...serverData };
    this.setLoading(true);
    await getServerData(serverData, (data) => {
      // console.log("data", data)
      if (!data || variableTypeOf(data) !== TypeEnum.array) return;
      if (refreshTable === true) {
        this.setState({ localDataSource: data }, () => {
          const { pagination, sortOrderColumns } = this.state;
          if (pagination === false) return;
          const pageNo: number = pagination.current ?? pagination.defaultCurrent!;
          const pageSize: number = pagination.pageSize ?? pagination.defaultPageSize!;
          const res = this.reloadByClient(pageNo, pageSize, sortOrderColumns);
          res.updateState();
        });
      } else {
        this.setState({ localDataSource: data });
      }
    }).finally(() => this.setLoading(false));
  }

  /**
   * 获取当前表格分页状态
   */
  public getPagination(): DataTableState['pagination'] {
    return this.state.pagination;
  }

  /**
   * 获取当前数据
   */
  public getDataSource(): TableRowData[] {
    return this.state.dataSource;
  }

  /**
   * 获取客户端数据
   */
  public getLocalDataSource(): undefined | TableRowData[] {
    return this.state.localDataSource;
  }

  /**
   * 更新当前数据
   */
  public setDataSource(dataSource: TableRowData[]): void {
    this.setState({ dataSource });
  }

  /**
   * 更新客户端数据
   */
  public setLocalDataSource(localDataSource: TableRowData[]): void {
    this.setState({ localDataSource });
  }

  /**
   * 获取表格当前选中行数据key
   */
  public getSelectedRowKeys(): TableRowSelection<TableRowData>['selectedRowKeys'] {
    return this.state.selectedRowKeys;
  }

  /**
   * 获取表格当前选中行数据
   */
  public getSelectedRows(): TableRowData[] {
    return this.selectedRows;
  }

  /**
   * 设置表格当前选中行数据key
   */
  public setSelectedRowKeys(selectedRowKeys: TableRowSelection<TableRowData>['selectedRowKeys']): void {
    this.setState({ selectedRowKeys: selectedRowKeys || [] });
    if (!selectedRowKeys) return;
    // 设置 selectedRows
    const rowKey = this.props.rowKey || this.props.tableProps?.rowKey;
    const data: TableRowData[] = this.state.localDataSource || this.state.dataSource;
    let selectedRows: TableRowData[] | undefined = undefined;
    if (rowKey instanceof Function) {
      selectedRows = data.filter((value) => {
        const keyValue = variableTypeOf(value) === TypeEnum.object ? rowKey(value) : undefined;
        if (!keyValue) return false;
        return selectedRowKeys.indexOf(keyValue) !== -1;
      });
    } else if (rowKey) {
      selectedRows = data.filter((value) => {
        const keyValue = variableTypeOf(value) === TypeEnum.object ? value[rowKey] : undefined;
        if (!keyValue) return false;
        return selectedRowKeys.indexOf(keyValue) !== -1;
      });
    }
    if (selectedRows) {
      this.selectedRows = selectedRows;
    }
  }
}

export { DataTableProps, DataTableState, DataTable };
